<template>
  <section class="main">
    <div class="crumbs">
      <el-breadcrumb separator="/">
        <el-breadcrumb-item><i class="el-icon-lx-copy"></i> 分类管理 </el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <div class="container">
      <div class="head">
        <el-scrollbar class="drag-box-item cache-pool-box">
          <draggable
            v-model="cachePool"
            @remove="removeHandle"
            filter=".forbid"
            :move="moveHandle"
            :options="dragOptions"
            class="cache-pool-drag"
            id="cache-pool"
          >
            <div v-for="item in cachePool" class="drag-list" :key="item.id">
              <span class="name">
                {{ item.name }}
              </span>
              <span class="operation">
                <span>
                  {{ item.id }}
                </span>
                <el-tooltip content="从缓存池中移除" :open-delay="600">
                  <el-button type="text" icon="el-icon-circle-close" @click="cachePoolDel(item)"></el-button>
                </el-tooltip>
              </span>
            </div>
            <div v-if="!cachePool.length" class="placeholder forbid"><i class="el-icon-files"></i>&nbsp; 将项目拖至此处来缓存</div>
          </draggable>
        </el-scrollbar>
      </div>
      <div class="drag-box">
        <div class="drag-box-item flex-col" v-for="(classify, index) in list" :key="index">
          <div class="item-title">
            {{ '一二三'[index] }}级分类
            <span class="describe" v-if="classifys[index - 1]">
              {{ classifys[index - 1].name }}<template v-if="classifys[index - 1].id">({{ classifys[index - 1].id }}) </template>
            </span>

            <el-input-number
              placeholder="栏目列数"
              v-if="index === 0"
              v-model="column"
              :max="17"
              :min="0"
              size="small"
              @change="getClassify(0, { id: column })"
              class="column-input"
            />
            <span>
              <el-button type="text" size="medium" icon="el-icon-refresh" @click="refresh(index)">刷新</el-button>
              <el-button
                v-if="power.includes('classify.add')"
                type="text"
                size="medium"
                icon="el-icon-circle-plus-outline"
                @click="showAdd(index)"
                >新增</el-button
              >
            </span>
          </div>
          <el-scrollbar class="item-ul" v-loading="loading[index]">
            <draggable
              :disabled="!power.includes('classify.edit')"
              v-model="list[index]"
              @remove="removeHandle"
              :move="moveHandle"
              :options="{ ...dragOptions }"
              class="draggable"
              :id="index"
            >
              <div
                v-for="item in classify.slice(0, 200)"
                class="drag-list"
                @click.self="select(index, item)"
                :class="{ active: isActive(index, item) }"
                :key="item.id"
              >
                <span class="name" @dblclick="showRename(item)">
                  {{ item.name }}
                </span>
                <span class="operation">
                  <span>
                    {{ item.id }}
                  </span>
                  <el-popconfirm title="确认删除？" @confirm="del(item)">
                    <template #reference>
                      <el-button type="text" icon="el-icon-circle-close"></el-button>
                    </template>
                  </el-popconfirm>
                </span>
              </div>
            </draggable>
          </el-scrollbar>
        </div>
        <div class="drag-box-item record-box">
          <div class="item-title">
            操作记录
            <span>
              <el-button v-if="power.includes('classify.edit')" type="text" size="medium" icon="el-icon-refresh" @click="reloadRecord">
                刷新
              </el-button>
            </span>
          </div>
          <el-scrollbar class="item-ul" v-if="power.includes('classify.edit')">
            <div :infinite-scroll-distance="10" v-infinite-scroll="getRecord" :infinite-scroll-disabled="infiniteDisabled">
              <el-popover
                v-for="item in recordList"
                :key="item.id"
                placement="top-start"
                :title="operationMap[item.type]"
                width="180"
                trigger="hover"
              >
                <template #reference>
                  <div class="record-item">
                    <div class="text">{{ operationMap[item.type] }}操作</div>
                    <div class="date">{{ item.createdAt | date }}</div>
                    <div>
                      <el-button type="text" @click="reduction(item)"> 还原 </el-button>
                    </div>
                  </div>
                </template>
                <template>
                  <template v-if="item.type === 'new'">
                    新增({{ item.grade }})级分类[{{ item.name }}]
                    <br />
                    父分类: {{ item.parent }}
                  </template>
                  <template v-else-if="item.type === 'move'">
                    移动{{ item.oldname }}到({{ item.grade }})级分类
                    <br />
                    父分类: {{ item.parent }}
                  </template>
                  <template v-else-if="item.type === 'del'"> 删除分类[id:{{ item.classifyid }}] </template>
                  <template v-else-if="item.type === 'rename'">
                    重命名[{{ item.oldname }}]到[{{ item.name }}]
                    <br />
                    等级: {{ item.grade }}
                    <br />
                    父分类: {{ item.parent }}
                  </template>
                </template>
              </el-popover>
            </div>
          </el-scrollbar>
          <div v-else class="item-ul no-power">您无权查看操作记录</div>
        </div>
      </div>
      <el-dialog v-drag :title="`添加${'一二三'[form.grade]}级分类`" :visible.sync="showAddDialog" width="20%">
        <template>
          <el-input v-model="form.name" clearable placeholder="输入分类名称" />
        </template>
        <template v-slot:footer>
          <el-button @click="add()" type="primary">保 存</el-button>
          <el-button @click="showAddDialog = false">关 闭</el-button>
        </template>
      </el-dialog>
      <el-dialog v-drag title="重命名" :visible.sync="showRenameDialog" width="20%">
        <template>
          <el-input v-model="form.name" clearable placeholder="输入分类名称" />
        </template>
        <template v-slot:footer>
          <el-button @click="rename()" type="primary">保 存</el-button>
          <el-button @click="showRenameDialog = false">关 闭</el-button>
        </template>
      </el-dialog>
    </div>
  </section>
</template>

<script>
import { classifyList, classifyAdd, classifyDel, classifyRename, classifyMove, classifyRecord, classifyReduction } from '@/api/classify'
import { mapGetters } from 'vuex'

import draggable from 'vuedraggable'
export default {
  name: 'classify',
  data() {
    return {
      /**所有分类 */
      list: [[], [], []],
      /**活跃分类 */
      classifys: [],
      /**加载动画 */
      loading: [],
      /**显示新增分类 */
      showAddDialog: false,
      /**显示重命名分类 */
      showRenameDialog: false,
      form: {
        /**新增分类等级 */
        parent: 0,
        /**新增分类名字 */
        name: '',
      },
      /**栏目 */
      column: 0,
      /**缓存池 */
      cachePool: [],
      query: {
        size: 10,
        page: 0,
      },
      /**操作记录 */
      recordList: [],
      /**操作记录Loading */
      recordLoading: false,
      infiniteDisabled: false,
      /**操作映射 */
      operationMap: {
        new: '新增',
        move: '移动',
        rename: '重命名',
        del: '删除',
      },
      dragOptions: {
        animation: 120,
        scroll: true,
        group: 'list',
        sort: false,
        ghostClass: 'ghost-style',
      },
    }
  },
  computed: {
    ...mapGetters('user', ['power']),
  },
  components: {
    draggable,
  },
  methods: {
    async getClassify(grade, parent) {
      this.$set(this.loading, grade, true)
      const data = await classifyList({ grade, parent: parent && parent.id })
      this.$set(this.loading, grade, false)
      if (data.code !== 200) return this.$message.error('获取分类列表失败，错误码:' + data.code)
      this.list[grade] = data.data
      return data
    },
    /**选择 */
    select(index, item) {
      if (this.isActive(index, item)) {
        this.$set(this.classifys, index, { name: '所有' })
        if (index < 2) this.getClassify(index + 1)
      } else {
        this.$set(this.classifys, index, item)
        if (index < 2) this.getClassify(index + 1, item)
      }
    },
    /**是否高亮 */
    isActive(index, item) {
      if (!this.classifys[index]) return
      return this.classifys[index].id === item.id
    },
    /**刷新 */
    refresh(index) {
      const item = this.classifys[index - 1]
      if (index === 0) {
        this.getClassify(index, { id: this.column })
      } else if (item) {
        this.getClassify(index, item)
      } else {
        this.getClassify(index, { name: '所有' })
      }
    },
    /**拖动完成钩子 */
    async removeHandle({ from, to, newIndex }) {
      if (to.id === 'cache-pool') return
      const item = this.list[to.id][newIndex]
      const parent = to.id === '0' ? this.column : this.classifys[to.id - 1].id
      if (item.parent === parent) return
      const grade = to.id
      const data = await classifyMove({ id: item.id, parent, grade })
      if (data.code !== 200) return this.$message.error('移动失败,请刷新页面重试,错误码:' + data.code)
      this.$message.success(`移动 [ ${item.name} ] 到${'一二三'[grade]}级分类`)
      this.reloadRecord()
    },
    /**拖动钩子 */
    moveHandle({ from, to, draggedContext: { element }, relatedContext: { list } }) {
      if (to.id === 'cache-pool') return true
      if (list && list.some((e) => e.id === element.id)) return false
      if (to.id === '0') {
        if (this.column === '') return false
        return true
      }
      const parent = this.classifys[to.id - 1]
      if (!parent) return false
    },
    /**显示新增分类窗口 */
    showAdd(grade, parent) {
      if (grade === 0) {
        if (this.column === '') return this.$message.warning(`请先选择分类栏目`)
        this.form.parent = this.column
      } else {
        if (!this.classifys[grade - 1]) return this.$message.warning(`请先选择${'一二三'[grade - 1]}级分类`)
        this.form.parent = this.classifys[grade - 1].id
      }
      this.form.grade = grade
      this.showAddDialog = true
    },
    /**显示重命名窗口 */
    showRename(item) {
      if (!this.power.includes('classify.edit')) return
      this.form = { ...item }
      this.showRenameDialog = true
    },
    /**新增分类 */
    async add() {
      const data = await classifyAdd(this.form)
      if (data.code !== 200) return this.$message.error('新增分类失败,错误码:' + data.code)
      this.$message.success('新增成功')
      this.refresh(this.form.grade)
      this.form = {}
      this.showAddDialog = false
      this.reloadRecord()
    },
    /**重命名 */
    async rename() {
      const data = await classifyRename(this.form)
      if (data.code !== 200) return this.$message.error('重命名失败,错误码:' + data.code)
      this.$message.success('重命名成功')
      this.refresh(this.form.grade)
      this.form = {}
      this.showRenameDialog = false
      this.reloadRecord()
    },
    /**删除分类 */
    async del(item) {
      const data = await classifyDel(item)
      if (data.code !== 200) return this.$message.error('删除分类失败,错误码:' + data.code)
      this.$message.success('删除成功')
      this.refresh(item.grade)
      this.reloadRecord()
    },
    /**删除缓存池 */
    cachePoolDel(item) {
      this.cachePool.splice(this.cachePool.indexOf(item), 1)
    },
    /**获取操作记录 */
    async getRecord() {
      this.recordLoading = true
      this.query.page++
      const data = await classifyRecord(this.query)
      this.recordList.push(...data.data)
      if (this.recordList.length >= data.total) this.infiniteDisabled = true
      this.recordLoading = false
    },
    /**刷新操作记录 */
    reloadRecord() {
      const bl = this.recordList.length === 0
      this.recordList = []
      this.infiniteDisabled = false
      this.query.page = 0
      if (bl) this.getRecord()
    },
    /**还原 */
    async reduction(item) {
      const data = await classifyReduction(item)
      if (data.code !== 200) return this.$message.error('还原失败,错误码:' + data.code)
      this.$message.success('还原成功')
      this.reloadRecord()
    },
  },
  created() {
    this.getClassify(0, { id: 0 })
  },
}
</script>

<style lang="scss" scoped>
.drag-box {
  display: flex;
  user-select: none;
}

.drag-box-item {
  background-color: #eff1f5;
  margin-right: 16px;
  border-radius: 6px;
  border: 1px #e1e4e8 solid;
  box-sizing: border-box;
  &.flex-col {
    flex: 1;
    min-width: 320px;
  }
  &.record-box {
    width: 280px;
    font-size: 14px;
  }
}
.item-title {
  padding: 8px 8px 8px 12px;
  font-size: 14px;
  line-height: 1.5;
  color: #24292e;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.item-ul {
  padding: 0 8px 8px;
  height: 500px;
}
.item-ul::-webkit-scrollbar {
  width: 0;
}
.head {
  display: flex;
  margin-bottom: 16px;
  .cache-pool-box {
    flex: 1;
    // margin-left: 16px;
    height: 120px;
    .cache-pool-drag {
      min-height: 120px;
      .drag-list {
        display: inline-block;
        width: auto;
        margin: 8px;
      }
    }
    .operation {
      padding: 0 6px;
    }
    .el-popconfirm {
      display: none;
    }
    .placeholder {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #8492a6;
    }
  }
}
.drag-box-item {
  .item-title {
    .describe {
      font-weight: initial;
      color: #8492a6;
    }
  }
  .column-input {
    width: 120px;
  }
  .drag-list {
    border: 1px #e1e4e8 solid;
    padding: 0 10px;
    height: 36px;
    margin: 5px 0 10px;
    list-style: none;
    background-color: #fff;
    border-radius: 6px;
    cursor: pointer;
    -webkit-transition: border 0.3s ease-in;
    transition: border 0.3s ease-in;
    line-height: 36px;
    .name {
      color: #333;
    }
    .operation {
      color: #8492a6;
      float: right;
      .el-button {
        margin-left: 8px;
      }
    }
  }
}

.no-power {
  display: flex;
  justify-content: center;
  align-items: center;
  color: #8492a6;
}

.record-item {
  display: flex;
  justify-content: space-between;
  line-height: 36px;
}

.draggable {
  min-height: 420px;
}
.drag-list:hover,
.drag-list.active {
  border: 1px solid #20a0ff;
}
.drag-title {
  font-weight: 400;
  line-height: 25px;
  margin: 10px 0;
  font-size: 22px;
  color: #1f2f3d;
}
.ghost-style {
  display: block;
  color: transparent;
  border-style: dashed;
}
</style>
